
Enum OnPremOrCloud {
    Undefined 
    SaaS_In_Cloud
    On_Premises
}

Enum OnPremOrAzure {
    Undefined
    In_Azure
    On_Premises
}

Enum ExtendedBool {
    Undefined
    True
    False
}

class LSInsightServer {
    [ExtendedBool]$UseExisting
    [string]$Name
    [string]$FullyQualifiedDomainName
    [PSCredential]$Credential
    [string]$UserName

    [LSInsightServer] Clone () {
        [LSInsightServer]$newObj = [LSInsightServer]::new()
        $newObj.UseExisting = $this.UseExisting
        $newObj.Name = $this.Name
        $newObj.FullyQualifiedDomainName = $this.FullyQualifiedDomainName
        $newObj.Credential = $this.Credential
        $newObj.UserName = $this.UserName
        return $newObj
    }
}

class LSInsightDatabase {
    [ExtendedBool]$UseExisting
    [string]$Name
    [string]$PricingTier

    [LSInsightDatabase] Clone () {
        [LSInsightDatabase]$newObj = [LSInsightDatabase]::new()
        $newObj.UseExisting = $this.UseExisting
        $newObj.Name = $this.Name
        $newObj.PricingTier = $this.PricingTier
        return $newObj
    }
}

class ADFv2 {
    [string]$Name
    [datetime]$TriggerStart

    [ADFv2] Clone () {
        [ADFv2]$newObj = [ADFv2]::new()
        $newObj.Name = $this.Name
        $newObj.TriggerStart = $this.TriggerStart
        return $newObj
    }
}

class ExtensionParameters {
    [string]$Name
    [string]$ProjectFolder
    [string]$ADFv2
    [string]$ResourceGroup
    [PSCredential]$LSCentral
    [PSCredential]$LSInsight

    [ExtensionParameters] Clone () {
        [ExtensionParameters]$newObj = [ExtensionParameters]::new()
        $newObj.Name = $this.Name
        $newObj.ProjectFolder = $this.ProjectFolder
        $newObj.ADFv2 = $this.ADFv2
        $newObj.ResourceGroup = $this.ResourceGroup
        $newObj.LSCentral = $this.LSCentral
        $newObj.LSInsight = $this.LSInsight
        return $newObj
    }
}

class LSInsightParameters {
    [OnPremOrAzure]$Placement
    [string]$Location
    [LSInsightServer]$Server
    [LSInsightDatabase]$Database
    [ADFv2]$ADFv2
    [ExtensionParameters]$Extension
    [string]$ClientIPAddress
    [string]$ProjectFolder
    [string]$ParametersOutFilePath
    [string]$ArmTemplateFile
    [string]$ArmTemplateParameterFile
    
    LSInsightParameters () {
        $this.Server = New-Object -TypeName 'LSInsightServer'
        $this.Database = New-Object -TypeName 'LSInsightDatabase'
        $this.ADFv2 = New-Object -TypeName 'ADFv2'
        $this.Extension = New-Object -TypeName 'ExtensionParameters'
    }

    [LSInsightParameters] Clone () {
        [LSInsightParameters]$newObj = [LSInsightParameters]::new()
        $newObj.Placement = $this.Placement
        $newObj.Location = $this.Location
        $newObj.Server = $this.Server.Clone()
        $newObj.Database = $this.Database.Clone()
        $newObj.ADFv2 = $this.ADFv2.Clone()
        $newObj.Extension = $this.Extension.Clone()
        $newObj.ClientIPAddress = $this.ClientIPAddress
        $newObj.ProjectFolder = $this.ProjectFolder
        $newObj.ParametersOutFilePath = $this.ParametersOutFilePath
        $newObj.ArmTemplateFile = $this.ArmTemplateFile
        $newObj.ArmTemplateParameterFile = $this.ArmTemplateParameterFile
        return $newObj
    }
}

class AzureParameters {
    [string]$ResourceGroup
    [string]$SubscriptionId

    [AzureParameters] Clone () {
        [AzureParameters]$newObj = [AzureParameters]::new()
        $newObj.ResourceGroup = $this.ResourceGroup
        $newObj.SubscriptionId = $this.SubscriptionId
        return $newObj
    }
}

class LSCentralParameters {
    [OnPremOrCloud]$Placement
    [string[]]$Companies
    [LSCentralServer]$Server
    [LSCentralDatabase]$Database

    LSCentralParameters () {
        $this.Server = New-Object -TypeName 'LSCentralServer'
        $this.Database = New-Object -TypeName 'LSCentralDatabase'
    }

    [LSCentralParameters] Clone () {
        [LSCentralParameters]$newObj = [LSCentralParameters]::new()
        $newObj.Placement = $this.Placement
        $newObj.Companies = $this.Companies
        $newObj.Server = $this.Server.Clone()
        $newObj.Database = $this.Database.Clone()
        return $newObj
    }

    [bool] HasQueriableParams () {
        $cond1 = ![string]::IsNullOrEmpty($this.Server.Name)
        $cond2 = $null -ne $this.Server.Credential
        $cond3 = ![string]::IsNullOrEmpty($this.Database.Name)
        
        return $cond1 -and $cond2 -and $cond3
    }
}

class LSCentralServer {
    [string]$Name
    [PSCredential]$Credential
    [string]$UserName
    [bool]$ConfirmedButNotConnectable

    [LSCentralServer] Clone () {
        [LSCentralServer]$newObj = [LSCentralServer]::new()
        $newObj.Name = $this.Name
        $newObj.UserName = $this.UserName
        $newObj.Credential = $newObj.Credential
        $newObj.ConfirmedButNotConnectable = $this.ConfirmedButNotConnectable
        return $newObj
    }
}

class LSCentralDatabase {
    [ExtendedBool]$UseExisting
    [string]$Name

    [LSCentralDatabase] Clone () {
        [LSCentralDatabase]$newObj = [LSCentralDatabase]::new()
        $newObj.UseExisting = $this.UseExisting
        $newObj.Name = $this.Name
        return $newObj
    }
}

class Parameters {
    [LSCentralParameters]$LSCentral
    [LSInsightParameters]$LSInsight
    [AzureParameters]$Azure
    [bool]$ConfirmAll
    
    Parameters () {
        $this.LSInsight = New-Object -TypeName 'LSInsightParameters'
        $this.LSCentral = New-Object -TypeName 'LSCentralParameters'
        $this.Azure = New-Object -TypeName 'AzureParameters'
    }

    [Parameters] Clone () {
        [Parameters]$newObj = [Parameters]::new()
        $newObj.LSCentral = $this.LSCentral.Clone()
        $newObj.LSInsight = $this.LSInsight.Clone()
        $newObj.Azure = $this.Azure.Clone()
        $newObj.ConfirmAll = $this.ConfirmAll
        return $newObj
    }
}

# Get the path to the function files.
$functionPath = $PSScriptRoot + "\Functions\"

# Get a list of all the function file names.
$functionList = Get-ChildItem -Path $functionPath -Name

# Loop over all the files and dot source them into memory.
foreach ($function in $functionList) {
    . ($functionPath + $function)
}
